package sdkshell.kuaiyan.com.kuaiyansdk.util;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.text.TextUtils;

import com.wmcsk.KuaiyanSdk;
import com.wmcsk.dl.dl.utils.DL;
import com.wmcsk.dl.util.LogUtils;
import com.wmcsk.dl.util.Md5Utils;
import com.wmcsk.dl.util.SPUtil;

import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.FileChannel;

import sdkshell.kuaiyan.com.kuaiyansdk.BuildConfig;
import sdkshell.kuaiyan.com.kuaiyansdk.SdkInit;
import sdkshell.kuaiyan.com.kuaiyansdk.bean.ApkNames;
import sdkshell.kuaiyan.com.kuaiyansdk.bean.LocalPluginBean;

import static sdkshell.kuaiyan.com.kuaiyansdk.util.PluginUtil.getSdkVersion;


/**
 * Created by 刘红亮 on 2015/6/23 13:39
 */
public class FileUtil {
    public static final int ONE_KB = 1024;
    public static final long ONE_MB = ONE_KB * ONE_KB;
    private static final long FILE_COPY_BUFFER_SIZE = ONE_MB * 10;
    public static final String INSTALL_PATH = "sdcard";
    public static final String ASSERT_TEMP_PATH = "assertTemp";
    public static final String NETWORK_PATH = "network";
    public static final String APK_NAME = "sdkPlugin.apk";
    /**
     * 获取下载目录
     * @param context
     * @return
     */
    public static File getDownCacheDir(Context context, String path) {
        File file = context.getDir("kyplugin", Context.MODE_PRIVATE);
        File sibuHost = new File(file,path);
        if (!sibuHost.exists()) {
            sibuHost.mkdirs();
        }
        return sibuHost;
    }
    /**
     * 筛选出本地最新版本
     */
    public static LocalPluginBean firstCopyAssert(Context context, String apkName){
        String sdkPluginInfo = SPUtil.getString(context, ApkNames.get(apkName),"");
        File destFile = null;
        double pluginVersion = -1;
        int sdkVersion = -1;
        String pluginPath = null;
        if(TextUtils.isEmpty(sdkPluginInfo)){
            try {
                InputStream is = context.getAssets().open(apkName);
                destFile = new File(getDownCacheDir(context,INSTALL_PATH).getAbsolutePath(), apkName);
                boolean isSuccess = doCopyFile(is, destFile);
                if(!isSuccess){
                    throw new RuntimeException("copy assert sdkPlugin.apk faild");
                }
            }catch (Exception e){
                e.printStackTrace();
                LogUtils.getNewInstance(KuaiyanSdk.ERROR_TAG).eob("copy assert sdkPlugin.apk 失败"+e.getMessage());
            }
            if(destFile == null){
                return null;
            }
            sdkVersion = getSdkVersion(destFile.getAbsolutePath(),context);
            pluginPath = destFile.getAbsolutePath();
            pluginVersion = PluginUtil.getPluginVersion(destFile.getAbsolutePath(),context);
        }else{
            try{
                JSONObject jsonObject = new JSONObject(sdkPluginInfo);
                pluginPath = jsonObject.optString("pluginPath");
                pluginVersion = jsonObject.optDouble("pluginVersion");
                sdkVersion = jsonObject.optInt("sdkVersion");
                String tempPlugin = copyTempSdk(context,apkName);
                if(tempPlugin != null){
                    int tempPluginSdkVersion = getSdkVersion(tempPlugin,context);
                    double tempPluginVersion = PluginUtil.getPluginVersion(tempPlugin,context);
                    if(tempPluginSdkVersion!= BuildConfig.VERSION_CODE){
                        throw new RuntimeException("版本不一致，sdk内部错误,SDK VERSION="+BuildConfig.VERSION_CODE+"  plugin SDK VERSION="+tempPluginSdkVersion);
                    }
                    if(!localPluginCanUser(pluginPath)){
                        pluginPath = new File(getDownCacheDir(SdkInit.getContext(),INSTALL_PATH),apkName).getAbsolutePath();
                        doCopyFile(new File(tempPlugin), new File(pluginPath), false);
                        sdkVersion = tempPluginSdkVersion;
                        pluginVersion = tempPluginVersion;
                    }else {
                        if (tempPluginVersion == pluginVersion) {
                            String pluginMd5 = Md5Utils.getMD5(pluginPath);
                            String tempPluginMd5 = Md5Utils.getMD5(tempPlugin);
                            //如果assert目录md5与插件md5不一致
                            if (!pluginMd5.equals(tempPluginMd5)) {
                                doCopyFile(new File(tempPlugin), new File(pluginPath), false);
                            }
                        } else if (tempPluginVersion > pluginVersion) {
                            doCopyFile(new File(tempPlugin), new File(pluginPath), false);
                            pluginVersion = tempPluginVersion;
                        }
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
        LocalPluginBean localPluginBean = new LocalPluginBean();
        localPluginBean.installPath = pluginPath;
        localPluginBean.sdkVersion = sdkVersion;
        localPluginBean.pluginVersion = pluginVersion;
        return localPluginBean;
    }

    public static boolean localPluginCanUser(String pluginPath){
        if(pluginPath == null){
            return false;
        }
        File file = new File(pluginPath);
        if(!file.exists()){
            return false;
        }
        int localPluginSdkVersion = getSdkVersion(pluginPath, SdkInit.getContext());
        if(localPluginSdkVersion!= BuildConfig.VERSION_CODE){
            LogUtils.getNewInstance(KuaiyanSdk.ERROR_TAG).eob("本地插件不可用 pluginSdkVersion = "+ localPluginSdkVersion+"  currentSdkVersion = "+BuildConfig.VERSION_CODE);
            return false;
        }
        return true;
    }

    /**
     * 将assert目录拷贝到临时目录，提供sd卡和assert版本对比
     * @param context
     * @return 拷贝之后的目录
     */
    public static String copyTempSdk(Context context, String apkName){
        File destFile = null;
        try {
            InputStream is = context.getAssets().open(apkName);
            destFile = new File(getDownCacheDir(context,ASSERT_TEMP_PATH).getAbsolutePath(), apkName);
            boolean isSuccess = doCopyFile(is, destFile);
            if(!isSuccess){
                throw new RuntimeException("copy assert "+apkName+" faild");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return destFile == null?null:destFile.getAbsolutePath();
    }

    public static PackageInfo getPackageInfo(String apkPath, Context context){
        PackageManager pm = context.getPackageManager();
        PackageInfo info = pm.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES);
        return info;
    }


    public static boolean doCopyFile(InputStream is, File destFile) throws IOException {
        if (is == null) {
            DL.e("is is null!");
            return false;
        }
        if(!destFile.exists()){
            destFile.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(destFile);
        byte[] buffer = new byte[ONE_KB * 2];
        int n;
        int size = 0;
        while ((n = is.read(buffer)) != -1) {
            fos.write(buffer, 0, n);
            size += n;
        }
        is.close();
        fos.close();
        DL.e("length="+destFile.length());
        if (size == destFile.length()) {
            return true;
        }
        return false;
    }

    public static void doCopyFile(File srcFile, File destFile,
                                  boolean preserveFileDate) throws IOException {
        if (destFile.exists() && destFile.isDirectory()) {
            throw new IOException("Destination '" + destFile
                    + "' exists but is a directory");
        }
        FileInputStream fis = null;
        FileOutputStream fos = null;
        FileChannel input = null;
        FileChannel output = null;
        try {
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            input = fis.getChannel();
            output = fos.getChannel();
            long size = input.size();
            long pos = 0;
            long count = 0;
            while (pos < size) {
                count = (size - pos) > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE
                        : (size - pos);
                pos += output.transferFrom(input, pos, count);
            }
        } finally {
            IOUtils.closeQuietly(output);
            IOUtils.closeQuietly(fos);
            IOUtils.closeQuietly(input);
            IOUtils.closeQuietly(fis);
        }
        if (srcFile.length() != destFile.length()) {
            throw new IOException("Failed to copy full contents from '"
                    + srcFile + "' to '" + destFile + "'");
        }
        if (preserveFileDate) {
            destFile.setLastModified(srcFile.lastModified());
        }
    }

    public static LocalPluginBean copyAssert(Context context, String apkName){
        File destFile = null;
        InputStream is = null;
        try {
            is = context.getAssets().open(apkName);
            destFile = new File(getDownCacheDir(context,INSTALL_PATH).getAbsolutePath(), apkName);
            boolean isSuccess = doCopyFile(is, destFile);
            if(!isSuccess){
                throw new RuntimeException("copy assert sdkPlugin.apk faild");
            }
        }catch (Exception e){
            e.printStackTrace();
            LogUtils.getNewInstance(KuaiyanSdk.ERROR_TAG).eob("copy assert sdkPlugin.apk 失败"+e.getMessage());
        }finally {
            IOUtils.closeQuietly(is);
        }
        if(destFile == null||!destFile.exists()){
            return null;
        }
       int  version = getSdkVersion(destFile.getAbsolutePath(),context);
       double pluginVersion = PluginUtil.getPluginVersion(destFile.getAbsolutePath(),context);
       String pluginPath = destFile.getAbsolutePath();
       LocalPluginBean localPluginBean = new LocalPluginBean();
       localPluginBean.sdkVersion = version;
       localPluginBean.installPath = pluginPath;
        localPluginBean.pluginVersion = pluginVersion;
       return localPluginBean;
    }
}
